package com.queclink.ycm.common.qms;

import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author ZiXiang
 */
public class HexProtocolUtils {

    public static JSONObject protocolDecode(String proString) {
        JSONObject jSONObject = new JSONObject(true);
        try {
            String messageHeader = HexUtils.fromHexString(proString.substring(0, 8));
            jSONObject.put("messageHeader", messageHeader);
            proString = proString.substring(8);

            String messageType = HexUtils.hex2decimal(proString.substring(0, 2));
            switch (messageType) {
                case "0":
                    messageType = "+RESP:GTDMR";
                    break;
                case "1":
                    messageType = "+RESP:GTUPC";
                    break;
                case "2":
                    messageType = "+RESP:GTUPD";
                    break;
                default:
                    break;
            }
            jSONObject.put("messageType", messageType);
            proString = proString.substring(2);

            Integer messageLength = Integer.parseInt(proString.substring(0, 4), 16);
            jSONObject.put("messageLength", messageLength);
            proString = proString.substring(4);

            if (proString.startsWith("80")) {
                String deviceType = proString.substring(0, 6);
                jSONObject.put("deviceType", deviceType);
                proString = proString.substring(6);
                String deviceMngPtlVersion = proString.substring(0, 4);
                jSONObject.put("deviceMngPtlVersion", deviceMngPtlVersion);
                proString = proString.substring(4);
            } else {
                String deviceType = proString.substring(0, 2);
                jSONObject.put("deviceType", deviceType);
                proString = proString.substring(2);
                String deviceMngPtlVersion = proString.substring(0, 4);
                jSONObject.put("deviceMngPtlVersion", deviceMngPtlVersion);
                proString = proString.substring(4);
            }

            String uniqueId = HexUtils.hex2decimal(proString.substring(0, 16));
            jSONObject.put("uniqueId", uniqueId);
            proString = proString.substring(16);

            String reportMask = proString.substring(0, 8);
            jSONObject.put("reportMask", reportMask);
            proString = proString.substring(8);

            String binaryReportMask = CharacterTranslateUtils.hexString2binaryString(reportMask);
            char[] chars = binaryReportMask.toCharArray();
            int lastIndex = chars.length - 1;

            if (chars[lastIndex] == '1') {
                Integer deviceLength = proString.indexOf("00");
                if (deviceLength % 2 == 1) {
                    deviceLength += 1;
                }
                String devName = HexUtils.fromHexString(proString.substring(0, deviceLength));
                jSONObject.put("devName", devName);
                proString = proString.substring(deviceLength + 2);
            }

            if (chars[lastIndex - 1] == '1') {
                String hardVer = proString.substring(0, 4);
                jSONObject.put("hardVer", hardVer);
                proString = proString.substring(4);
            }

            if (chars[lastIndex - 18] == '1') {
                String TrackProtocolVersion = proString.substring(0, 4);
                jSONObject.put("TrackProtocolVersion", TrackProtocolVersion);
                proString = proString.substring(4);
            }

            if (chars[lastIndex - 2] == '1') {
                if ((Integer.parseInt(proString.substring(0, 2), 16)) >= 0x80) {
                    String firmVer = proString.substring(0, 8);
                    jSONObject.put("firmVer", firmVer);
                    proString = proString.substring(8);
                } else {
                    String firmVer = proString.substring(0, 6);
                    jSONObject.put("firmVer", firmVer);
                    proString = proString.substring(6);
                }
            }

            if (chars[lastIndex - 3] == '1') {
                if ((Integer.parseInt(proString.substring(0, 2), 16)) >= 0x80) {
                    String lstFirmVer = proString.substring(0, 8);
                    jSONObject.put("lstFirmVer", lstFirmVer);
                    proString = proString.substring(8);
                } else {
                    String lstFirmVer = proString.substring(0, 6);
                    jSONObject.put("lstFirmVer", lstFirmVer);
                    proString = proString.substring(6);
                }
            }

            if (chars[lastIndex - 4] == '1') {
                String firmUpdTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
                jSONObject.put("firmUpdTime", firmUpdTime);
                proString = proString.substring(10);
            }

            if (chars[lastIndex - 7] == '1') {
                String confVer = proString.substring(0, 4);
                jSONObject.put("confVer", confVer);
                proString = proString.substring(4);
            }

            if (chars[lastIndex - 8] == '1') {
                String lstConfVer = proString.substring(0, 4);
                jSONObject.put("lstConfVer", lstConfVer);
                proString = proString.substring(4);
            }

            if (chars[lastIndex - 9] == '1') {
                String confChgTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
                jSONObject.put("confChgTime", confChgTime);
                proString = proString.substring(10);
            }

            if (chars[lastIndex - 10] == '1') {
                Integer mainPowerCon = Integer.parseInt(proString.substring(0, 4), 16);
                jSONObject.put("mainPowerVo", mainPowerCon);
                proString = proString.substring(4);
            }

            if (chars[lastIndex - 11] == '1') {
                Integer mainPowerVo = Integer.parseInt(proString.substring(0, 4), 16);
                jSONObject.put("batVoltage", mainPowerVo);
                proString = proString.substring(4);
                Integer batPercent = Integer.parseInt(proString.substring(0, 2), 16);
                jSONObject.put("batPercent", batPercent);
                proString = proString.substring(2);

            }

            if (chars[lastIndex - 12] == '1') {
                //Network Info
                String NetworkInfo = proString.substring(0, 4);
                jSONObject.put("NetworkInfo", NetworkInfo);
                proString = proString.substring(4);
            }

            if (chars[lastIndex - 13] == '1') {
                //16进制转2进制
                int nGNSSState = (Integer.parseInt(proString.substring(0, 2), 16)) >> 6;
                int sateNumber = (Integer.parseInt(proString.substring(0, 2), 16)) & 0X3F;
                jSONObject.put("gsmState", nGNSSState);
                proString = proString.substring(2);
                if (sateNumber > 0) {
                    List<SatelliteValue> valueList = new ArrayList<>();
                    for (int i = 0; i < sateNumber; i++) {
                        SatelliteValue value = new SatelliteValue();
                        //Satellite(i) ID
                        value.setSatelliteid(Integer.parseInt(proString.substring(0, 2), 16));
                        proString = proString.substring(2);
                        //Satellite(i) Power
                        value.setSatellitepwoer(Integer.parseInt(proString.substring(0, 2), 16));
                        proString = proString.substring(2);
                        valueList.add(value);
                    }
                    jSONObject.put("sateNumber", valueList);
                }
                //Last GNSS HDOP
                Integer gpsFix = Integer.parseInt(proString.substring(0, 2), 16);
                jSONObject.put("gpsFix", gpsFix);
                proString = proString.substring(2);
                //GNSS UTC Time
                String gpsUtcTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
                jSONObject.put("gpsUtcTime", gpsUtcTime);
                proString = proString.substring(10);
            }

            if (chars[lastIndex - 14] == '1') {
                //SIM Status	1	0 – 4	
                Integer simStatus = Integer.parseInt(proString.substring(0, 2), 16);
                jSONObject.put("simStatus", simStatus);
                proString = proString.substring(2);
                //IMSI	8
                String imsi = proString.substring(0, 16);
                jSONObject.put("imsi", imsi);
                proString = proString.substring(16);
                //ICCID	10
                String iccid = proString.substring(0, 20);
                jSONObject.put("iccid", iccid);
                proString = proString.substring(20);
            }

            if (chars[lastIndex - 16] == '1') {
                //OBD Firmware Version	3	‘0’ – ‘9’, ‘A’ – ‘F’	
                String obdfirmVer = proString.substring(0, 6);
                jSONObject.put("obdfirmVer", obdfirmVer);
                proString = proString.substring(6);
                //OBD Last Firmware Version	3	‘0’ – ‘9’, ‘A’ – ‘F’
                String obdLstFirmVer = proString.substring(0, 6);
                jSONObject.put("obdLstFirmVer", obdLstFirmVer);
                proString = proString.substring(6);
                //OBD Firmware Change Time	5
                String obdfirmChgTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
                jSONObject.put("obdfirmChgTime", obdfirmChgTime);
                proString = proString.substring(10);
                //OBD Configuration Version	2	‘0’ – ‘9’, ‘A’ – ‘F’
                String obdConfVer = HexUtils.fromHexString(proString.substring(0, 4));
                jSONObject.put("obdConfVer", obdConfVer);
                proString = proString.substring(4);
                //OBD Last Configuration Version	2	‘0’ – ‘9’, ‘A’ – ‘F’
                String obdLstConfVer = HexUtils.fromHexString(proString.substring(0, 4));
                jSONObject.put("obdLstConfVer", obdLstConfVer);
                proString = proString.substring(4);
                //OBD Configuration Change Time	5
                String obdConfChgTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
                jSONObject.put("obdConfChgTime", obdConfChgTime);
                proString = proString.substring(10);
            }

            if (chars[lastIndex - 17] == '1') {
                //BT Firmware Version	2	‘0’ – ‘9’, ‘A’ – ‘F’
                String btFirmVer = proString.substring(0, 4);
                jSONObject.put("btFirmVer", btFirmVer);
                proString = proString.substring(4);
                //BT Last Firmware Version	2	‘0’ – ‘9’, ‘A’ – ‘F’	
                String btLstFirmVer = proString.substring(0, 4);
                jSONObject.put("btLstFirmVer", btLstFirmVer);
                proString = proString.substring(4);
                //BT Firmware Change Time	5	
                String btFirmChgTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
                jSONObject.put("btFirmChgTime", btFirmChgTime);
                proString = proString.substring(10);
            }

            if (messageType.equals("+RESP:GTUPC")) {
                String UPCFieldsMask = proString.substring(0, 2);
                jSONObject.put("UPCFieldsMask", UPCFieldsMask);
                proString = proString.substring(2);

                int cmdId = Integer.parseInt(proString.substring(0, 4), 16);
                jSONObject.put("cmdId", cmdId);
                proString = proString.substring(4);

                int code = Integer.parseInt(proString.substring(0, 4), 16);
                jSONObject.put("code", code);
                proString = proString.substring(4);

                //转2进制
                String upcMask = HexUtils.hexString2binaryString(UPCFieldsMask);
                char[] mask = upcMask.toCharArray();
                int last = mask.length - 1;
                if (mask[last] == '1') {
                    String identifierNumber = proString.substring(0, 8);
                    jSONObject.put("identifierNumber", identifierNumber);
                    proString = proString.substring(8);
                }
            }

            if (messageType.equals("+RESP:GTUPD")) {
                String UPCFieldsMask = proString.substring(0, 2);
                jSONObject.put("UPDFieldsMask", UPCFieldsMask);
                proString = proString.substring(2);

                int code = Integer.parseInt(proString.substring(0, 4), 16);
                jSONObject.put("code", code);
                proString = proString.substring(4);

                //转2进制
                String updMask = HexUtils.hexString2binaryString(UPCFieldsMask);
                char[] mask = updMask.toCharArray();
                int last = mask.length - 1;
                if (mask[last] == '1') {
                    String identifierNumber = proString.substring(0, 8);
                    jSONObject.put("identifierNumber", identifierNumber);
                    proString = proString.substring(8);
                }
            }
            //Send Time 5 YYYYMMDDHHMMSS 
            String msgTime = HexUtils.hexParseUpdateTime(proString.substring(0, 10));
            jSONObject.put("msgTime", msgTime);
            proString = proString.substring(10);

            //Count Number	2	0000 – FFFF
            String countNo = proString.substring(0, 4);
            jSONObject.put("countNo", countNo);
            proString = proString.substring(4);

            //Checksum  2
            String checksum = proString.substring(0, 4);
            jSONObject.put("checksum", checksum);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jSONObject;
    }

    public static JSONObject protocolACK(String proString) {
        JSONObject jSONObject = new JSONObject(true);
        String messageHeader = HexUtils.fromHexString(proString.substring(0, 8));
        jSONObject.put("messageHeader", messageHeader);
        proString = proString.substring(8);
        Integer messageType = Integer.parseInt(proString.substring(0, 2), 16);
        if (messageType == 52) {
            jSONObject.put("messageType", "AT+GTUPC");
        } else if (messageType == 21) {
            jSONObject.put("messageType", "AT+GTUPD");
        }
        proString = proString.substring(2);

        String reportMask = proString.substring(0, 2);
        String updMask = HexUtils.hexString2binaryString(reportMask);
        proString = proString.substring(2);

        char[] mask = updMask.toCharArray();
        int last = mask.length - 1;
        //length
        if (mask[last] == '1') {
            proString = proString.substring(2);
        }
        //deciceType
        if (mask[last - 1] == '1') {
            proString = proString.substring(2);
        }
        //Protocol Version
        if (mask[last - 2] == '1') {
            proString = proString.substring(4);
        }
        //Firmware Version
        if (mask[last - 3] == '1') {
            proString = proString.substring(4);
        }
        //imei
        if (mask[last - 4] == '0') {
            String uniqueId = HexUtils.hex2decimal(proString.substring(0, 16));
            jSONObject.put("uniqueId", uniqueId);
            proString = proString.substring(16);
        }
        //ID
        proString = proString.substring(2);
        //serialNumber
        String serialNumber = proString.substring(0, 4);
        jSONObject.put("serialNumber", serialNumber);
        return jSONObject;
    }

//    public static void main(String[] args) {
//        System.out.println(protocolDecode("2B48455802006E15040256345404073E4E0700047F9F475635314D4700010101000101070101071F8EC2B600000000001F8EC32CF930200FE164251F450C302B2E182D0D2D322A011F8EC2648A004600230025743310898600200917F20052210000641F8EC32E8B26BB37560D0A"));
//        System.out.println(protocolACK("2B41434B346F242F08060D0356261E030E29440200000A07E304170B3B3269FF60E20D0A"));
//    }
}
